﻿using System;
using System.Collections.Generic;
using System.Data.Objects;
using System.Linq;
using System.Text;
using nanoCMS.Core;
using nanoCMS.Forum.Concrete;
using nanoCMS.Forum.Providers;
using nanoCMS.Forum.WebUI.Models.AdminViewModels;
using nanoCMS.Forum.WebUI.Models.ViewModels;

namespace nanoCMS.Forum.WebUI.Models
{
    public class ForumAdminService
    {
        private readonly WorldContext worldContext;
        private readonly ForumProvider provider;
        private ThreadProvider threadProvider;
        private ForumProvider forumProvider;

        public ForumAdminService(WorldContext worldContext)
        {
            this.worldContext = worldContext;
            provider = new ForumProvider(this.worldContext);
            threadProvider = new ThreadProvider(this.worldContext);
            forumProvider = new ForumProvider(this.worldContext);
        }

        public List<ForumEntryVM> GetForumList()
        {
            return provider.GetAllForums().Select(VMFactory.ForumEntryVMFactory).ToList();
        }

        public List<ForumEntryVM> GetRootForumList()
        {
            return provider.GetRootForumList().Select(VMFactory.ForumEntryVMFactory).ToList();
        }

        public List<ForumTreeVM> BuldForumDisplayData(int selectedForumId = 0)
        {
            List<ForumEntryVM> roots = GetRootForumList();
            if (roots != null)
            {
                List<ForumTreeVM> tree = fillForumTree(roots, selectedForumId);
                foreach (var displayEntry in tree)
                {
                    fillForumDisplayDepth(displayEntry, 0);
                }
                return tree;
            }
            return null;
        }

        private List<ForumTreeVM> fillForumTree(List<ForumEntryVM> roots, int selectedForumId = 0)
        {
            List<ForumTreeVM> result = new List<ForumTreeVM>();
            foreach (var forum in roots)
            {
                List<ForumEntryVM> children = provider.GetSubForums(forum.ForumID).Select(VMFactory.ForumEntryVMFactory).ToList();
                ForumTreeVM treeEntry = new ForumTreeVM
                {
                    ForumEntry = forum,
                    Childern = fillForumTree(children, selectedForumId),
                    Selected = forum.ForumID == selectedForumId
                };
                result.Add(treeEntry);
            }
            return result;
        }

        private void fillForumDisplayDepth(ForumTreeVM tree, int depth)
        {
            tree.Depth = depth;
            foreach (var item in tree.Childern)
            {
                fillForumDisplayDepth(item, depth + 1);
            }
        }

        public ForumAdministrationVM CreateForumAdminModel()
        {
            ForumAdministrationVM model = new ForumAdministrationVM()
            {
                ForumEntry = new ForumEntryVM(),
                Forums = GetForumList(),
                ForumDisplay = BuldForumDisplayData()
            };
            return model;
        }

        public ForumAdministrationVM EditForumAdminModel(int forumId)
        {
            Concrete.Forum forum = provider.GetForum(forumId);
            if (forum == null)
            {
                return null;
            }
            ForumAdministrationVM model = new ForumAdministrationVM()
            {
                ForumEntry = VMFactory.ForumEntryVMFactory(forum),
                Forums = GetForumList(),
                ForumDisplay = BuldForumDisplayData(forumId)
            };
            return model;
        }

        public void CreateNewForum(ForumEntryVM forumEntryVM)
        {
            provider.Add(forumEntryVM.Title, forumEntryVM.Description, forumEntryVM.ParentForumID, RequestItems.TenantID);
        }

        public void EditNewForum(ForumEntryVM forumEntryVM)
        {
            provider.Edit(forumEntryVM.ForumID, forumEntryVM.Title, forumEntryVM.Description, forumEntryVM.ParentForumID);
        }

        /// <summary>
        /// Reorder forums in one forum level.
        /// </summary>
        /// <param name="forumID"></param>
        /// <param name="up">true if needs to move up (decrease forum order property)</param>
        public void ChangeForumOrder(int forumID, bool up)
        {
            provider.ChangeForumOrder(forumID, up);
        }

        public MoveThreadVM CreateMoveThreadModel(int threadID)
        {
            MoveThreadVM model = new MoveThreadVM
            {
                Thread = VMFactory.ThreadVMFactory(threadProvider.GetThread(threadID)),
                ForumDisplay = BuldForumDisplayData()
            };
            return model;
        }

        public void MoveThread(ThreadVM threadVM)
        {
            Thread thread = threadProvider.GetThread(threadVM.ThreadID);
            if (thread != null && threadVM.ForumID != 0)
            {
                // update old/new forum posts/threads
                if (thread.ForumID.HasValue)
                {
                    forumProvider.DecreaseForumPostCount(thread.ForumID.Value, thread.PostsCount);
                    forumProvider.DecreaseForumThreadCount(thread.ForumID.Value);
                }
                forumProvider.IncreaseForumPostCount(threadVM.ForumID, thread.PostsCount);
                forumProvider.IncreaseForumThreadCount(threadVM.ForumID);
                threadProvider.MoveThread(threadVM.ThreadID, threadVM.ForumID);
            }
        }
    }
}
